<?php
include_once(APP_PATH."/cartoon/global.php");
class cartoon_util_cache{
	private static $data = '';
	private $serialize = false;

	/**
	 * 创建目录
	 *
	 * @param unknown_type $path
	 * @return unknown
	 */
	
	public  function mkdirs($path){
		$path = trim($path);
		if (!$path) return false;
		do {
			$dir = $path;
			while (!is_dir($dir)) {
				$basedir = dirname($dir);
				if ($basedir == '/' || is_dir($basedir))
				mkdir($dir,0777);
				else
				$dir=$basedir;
			}
		} while ($dir != $path);
		return $path;
	}
	
	
	
	/**
	 * 分割数组
	 *
	 * @param unknown_type $array
	 * @param unknown_type $offset 开始位置
	 * @param unknown_type $len 长度
	 * @return unknown
	 */
	
	public function array_slice_key($array, $offset, $len=-1){
		if (!is_array($array)) 	return FALSE;
		$length = $len >= 0? $len: count($array);
		$keys = array_slice(array_keys($array), $offset, $length);
		foreach($keys as $key) {
			$return[$key] = $array[$key];
		}

		return $return;
	}
	
	
	/**
	 * 将数组转换成字符串，方便写入文件缓存
	 *
	 * @param unknown_type $array
	 * @param unknown_type $level 数组缩进
	 * @return unknown
	 */
	private function arrayeval($array, $level = 0) {
		$space = '';
		for($i = 0; $i <= $level; $i++) {
			$space .= "\t";
		}
		$evaluate = "Array\n$space(\n";
		$comma = $space;
		foreach($array as $key => $val) {
			$key = is_string($key) ? '\''.addcslashes($key, '\'\\').'\'' : $key;
			$val = !is_array($val) && (!preg_match("/^\-?\d+$/", $val) || strlen($val) > 12) ? '\''.addcslashes($val, '\'\\').'\'' : $val;
			if(is_array($val)) {
				$evaluate .= "$comma$key => ".$this->arrayeval($val, $level + 1);
			} else {
				$evaluate .= "$comma$key => $val";
			}
			$comma = ",\n$space";
		}
		$evaluate .= "\n$space)";
		return $evaluate;
	}
	
	/**
	 * 包含一个缓存文件,并返回内容
	 *
	 * @param unknown_type $filename 文件路径
	 * @param unknown_type $key 缓存文件的key
	 * @return unknown
	 */
	
	public function includeFile($filename,$key = ''){
		if(file_exists($filename)){
			@require_once($filename);
			!$key && $key = basename($filename,'.php');
			$key = "\$key=&\$".substr($key,strpos($key,'_')+1).";";
			eval($key);
			return $key;
		}
		else return false;
	}

	/**
	 * 读取文件
	 *
	 * @param unknown_type $filename
	 * @return unknown
	 */
	public function freadfile($filename) {
		$content = '';
		if(function_exists('file_get_contents')) {
			@$content = file_get_contents($filename);
		} else {
			if(@$fp = fopen($filename, 'r')) {
				$content = fread($fp, filesize($filename));
				@fclose($fp);
			}
		}
		return $content;
	}

	/**
	 * 写缓存文件
	 *
	 * @param unknown_type $filename
	 * @param unknown_type $writetext
	 * @param unknown_type $openmod
	 * @return unknown
	 */
	public  function writefile($filename, $writetext, $openmod='w') {
		@touch($filename);
		@chmod($filename,0777);
		if(@$fp = fopen($filename, $openmod)) {
			flock($fp, 2);
			fwrite($fp, $writetext);
			fclose($fp);
			return true;
		} else {
			return false;
		}
	}

	/**
 	* 写缓存文件
 	*
 	* @param unknown_type $data 缓存的数据
 	* @param unknown_type $key 数组的key
 	* @param unknown_type $filename 文件路径
 	* @return unknown
 	*/
	public function writeData($data,$key,$filename = ''){
		$data = is_array($data)?$data:array($data);
		$cachetext = "<?php\r\n".
		"/* This is a  Cache File Create On ".date('Y-m-d H:i:s',time())." Don't Change it!! */\r\n".
		'$'.$key.'='.($this->serialize?serialize($data):$this->arrayeval($data)).
		"\r\n?>";
		//print_r($cachetext);exit;
		return $this->writefile($filename, $cachetext);
	}
	
	/**
	 * 获取缓存数据
	 * @desc 参数$args 由三部分组成
	 * 						path:此为配置文件中的缓存路径 此路径是在配置文件中的cache_path指向的目录下建立目录，如果没有该目录，程序会字段创建
	 * 						filename:为主键，能标识唯一文件的。通常为主键id
	 * 						expire:为缓存时间，单位为秒 为0表示不过期
	 * @param unknown_type $args
	 * @param  array  $callback   取数据的回调函数 格式为：array( array('class','function'),array('参数'))
	 * @param unknown_type $flush 为True：立刻更新缓存 为False：过期则更新缓存 
	 * @return unknown
	 */
	public  function getCacheData($args = array('path'=>'','filename'=>'','expire' =>0),$callback=array(),$flush =false){
		if(! $args['path'] || !$args['filename']) return false;
		$filepath = $this->mkdirs(CT_CACHE_PATH.$args['path']);//文件路径
		$filename = $filepath."/cache_".$args['filename'].".php";	//文件名
		$changed = false;
		if (file_exists($filename)){
			$args['expire']=$args['expire']?$args['expire']:0;
			if(($args['expire']>0 && abs(time()-filemtime($filename))>=$args['expire']) || $flush===true){	//文件存在，但过期
				$changed = true;	
				@unlink($filename);
			}
		}else{
			$changed = true;	
		}
		if($changed){		//如果文件不存在
			$data = $this->getData($callback);
			if(!empty($data)){		//调用回调函数取回数据
				$this->writeData($data,$args['filename'],$filename);
			}
			return $data;		//返回数据
		}
		return $this->includeFile($filename);		//如果数据符合规范，直接返回
	}
	
	/**
	 * 回调用户自定义函数
	 *
	 * @param unknown_type $callback
	 * @return unknown
	 */
	private function getData($callback){
		list($fun,$arg) = $callback;
		if(is_array($fun) && is_object($fun[0]))
			$fun[0] = get_class($fun[0]);
		return call_user_func_array((array)$fun,(array)$arg);
	}
	
}